import { types } from "recast";

const {
  ifStatement,
  blockStatement,
  expressionStatement,
  assignmentExpression,
} = types.builders;

/**
 * 获取所有赋值语句，对其中的表达式进行分解
 */
const modifyAssignmentExpression = function (path) {
  const assignExp = path.node.expression;
  // 如果赋值表达式右侧为三元运算，则分解为if和else
  // 例子：a=b==2?3:4;
  if (assignExp.right.type == "ConditionalExpression") {
    const conditionExp = assignExp.right;
    const newStatement = ifStatement(
      conditionExp.test,
      blockStatement([
        expressionStatement(
          assignmentExpression("=", assignExp.left, conditionExp.consequent)
        ),
      ]),
      blockStatement([
        expressionStatement(
          assignmentExpression("=", assignExp.left, conditionExp.alternate)
        ),
      ])
    );

    const parentPath = path.insertAfter(newStatement);
    path.prune();
    parentPath.each((childPath) => {
      if (newStatement === childPath.node) {
        this.visit(childPath);
      }
    });
  } else if (assignExp.right.type == "LogicalExpression") {
    //修改声明初始化为逻辑表达式的语句
    // 例子: a=(b && b.name);
    const logicExp = assignExp.right;

    if (logicExp.operator === "&&") {
      const newStatement = ifStatement(
        logicExp.left,
        blockStatement([
          expressionStatement(
            assignmentExpression("=", assignExp.left, logicExp.right)
          ),
        ]),
        blockStatement([
          expressionStatement(
            assignmentExpression("=", assignExp.left, logicExp.left)
          ),
        ])
      );

      const parentPath = path.insertAfter(newStatement);
      path.prune();
      parentPath.each((childPath) => {
        if (newStatement === childPath.node) {
          this.visit(childPath);
        }
      });
    } else if (logicExp.operator === "||") {
      const newStatement = ifStatement(
        logicExp.left,
        blockStatement([
          expressionStatement(
            assignmentExpression("=", assignExp.left, logicExp.left)
          ),
        ]),
        blockStatement([
          expressionStatement(
            assignmentExpression("=", assignExp.left, logicExp.right)
          ),
        ])
      );
      const parentPath = path.insertAfter(newStatement);
      path.prune();
      parentPath.each((childPath) => {
        if (newStatement === childPath.node) {
          this.visit(childPath);
        }
      });
    }
  } else if (assignExp.right.type == "SequenceExpression") {
    const lastExp = assignExp.right.expressions.pop();
    const expressionStatements = assignExp.right.expressions.map((childExp) => {
      return expressionStatement(childExp);
    });
    const parentPath = path.insertBefore(...expressionStatements);
    assignExp.right = lastExp;
    parentPath.each((childPath) => {
      if (expressionStatements.includes(childPath.node)) {
        this.visit(childPath);
      }
    });
  }
};

export default modifyAssignmentExpression;
